package ru.aslanov.schedule.client;

import com.google.gwt.core.client.JavaScriptObject;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.util.BooleanCallback;
import com.smartgwt.client.util.JSOHelper;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Button;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.ClickEvent;
import com.smartgwt.client.widgets.events.ClickHandler;
import com.smartgwt.client.widgets.grid.ListGrid;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.HStack;
import com.smartgwt.client.widgets.layout.VLayout;
import ru.aslanov.schedule.client.ds.GCalendarDS;
import ru.aslanov.schedule.client.ds.UserGCalendarsDS;
import ru.aslanov.schedule.client.i18n.I18nUtil;
import ru.aslanov.schedule.client.util.*;
import ru.aslanov.schedule.shared.SyncStatus;

import static ru.aslanov.schedule.client.i18n.I18nUtil.cnt;
import static ru.aslanov.schedule.client.i18n.I18nUtil.msg;

/**
 * Created by IntelliJ IDEA.
 * Created: Feb 27, 2010 5:46:10 PM
 *
 * @author Sergey Aslanov
 */
public class GCalendarsPanel extends VLayout implements Invalidatable {
    private Label authorizationLabel;
    private Button sendToGoogleCalendar;
    private ScheduleUser scheduleUser;
    private Button removeAuthorization;
    private Label lastPublished;
    private Button downloadFromGCal;
    private GCalendarSyncData calendarSyncData;
    private Button authorizeInGoogleCalendar;
    private Button linkCalendarsButton;
    private ListGrid calendarsListGrid;


    public GCalendarsPanel(final GroupsPanel groupsPanel, final ScheduleUser scheduleUser) {
        super(10);

        HLayout buttons = new HLayout(5);
        buttons.setHeight(15);

        this.scheduleUser = scheduleUser;

        calendarsListGrid = new ListGrid();
        final String scheduleKey = scheduleUser.getScheduleKey();
        calendarsListGrid.setDataSource(GCalendarDS.getInstance(scheduleUser));
        calendarsListGrid.setWidth100();
        calendarsListGrid.setHeight100();
        calendarsListGrid.setShowAllRecords(true);
        calendarsListGrid.setAutoFetchData(true);
        calendarsListGrid.setCanEdit(false);
        calendarsListGrid.setWrapCells(true);
        calendarsListGrid.setFixedRecordHeights(false);
        calendarsListGrid.setUseAllDataSourceFields(true);

        /*
        ListGridField field = new ListGridField("calendarId");
        final SelectItem selectItem = new SelectItem("calendarId");
        selectItem.setOptionDataSource(UserGCalendarsDS.getInstance(scheduleKey));
        selectItem.setDisplayField("name");
        selectItem.setSortField("name");
        selectItem.setValueField("calendarId");
        selectItem.addChangedHandler(new ChangedHandler() {
            @Override
            public void onChanged(ChangedEvent changedEvent) {
                final String name = selectItem.getSelectedRecord().getAttribute("name");
                SC.logWarn("Setting name to '" + name + "'");
                listGrid.setEditValue(listGrid.getEditRow(), "name", name);
            }
        });
        field.setEditorType(selectItem);
        field.setDisplayField("name");
        listGrid.setFields(field);                
        */

                        
        authorizeInGoogleCalendar = new Button(cnt().authorizeInGCalendar());
        authorizeInGoogleCalendar.hide();
        authorizeInGoogleCalendar.setAutoFit(true);
        authorizeInGoogleCalendar.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent clickEvent) {
                String callbackName = JavaScriptMethodHelper.registerCallbackFunction(new JavaScriptMethodCallback() {
                    @Override
                    public void execute(JavaScriptObject obj) {
                        final boolean success = JSOHelper.getAttributeAsBoolean(obj, "success");
                        if (success) {
                            SC.say(cnt().operationSuccess());
                            calendarSyncData.refresh();
                        } else {
                            ErrorHandler.operationFailed(JSOHelper.getAttribute(obj, "message"));
                        }
                    }
                });
                com.google.gwt.user.client.Window.open("/gcalendar-auth?schedule=" + scheduleKey + "&callback=" + callbackName, "gcalendar-auth",
                        "width=700,height=450,menubar=0,toolbar=0,status=0,scrollbars=1,resizable=1");
            }
        });

        removeAuthorization = new Button(cnt().removeAuthorization());
        removeAuthorization.hide();
        removeAuthorization.setAutoFit(true);
        removeAuthorization.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent clickEvent) {
                ScheduleServices.App.getInstance().removeAuthorization(scheduleKey, new MyAsyncCallback<Void>(removeAuthorization) {
                    @Override
                    public void onSuccess(Void result) {
                        super.onSuccess(result);
                        calendarSyncData.refresh();
                    }
                });
            }
        });

        if (this.scheduleUser.isAdmin()) {
            downloadFromGCal = new Button(cnt().downloadFromGCal());
            downloadFromGCal.setAutoFit(true);
            downloadFromGCal.disable();
            downloadFromGCal.addClickHandler(new ClickHandler() {
                @Override
                public void onClick(final ClickEvent clickEvent) {
                    SC.ask(cnt().confirmDowloadFromGCal(), new BooleanCallback() {
                        @Override
                        public void execute(Boolean aBoolean) {
                            if (aBoolean) {
                                ScheduleServices.App.getInstance().loadFromGCalendar(scheduleKey, new MyAsyncCallback<Void>(downloadFromGCal) {
                                    @Override
                                    public void onSuccess(Void aVoid) {
                                        super.onSuccess(aVoid);
                                        calendarsListGrid.invalidateCache();
                                        groupsPanel.getGroupsGrid().invalidateCache();
                                    }
                                });
                            }
                        }
                    });
                }
            });
            buttons.addMember(downloadFromGCal);
        }


        sendToGoogleCalendar = new Button(cnt().sendToGCalendar());
        sendToGoogleCalendar.setAutoFit(true);
        sendToGoogleCalendar.disable();
        sendToGoogleCalendar.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(final ClickEvent clickEvent) {
                SC.confirm(cnt().areYouSure(), new BooleanCallback() {
                    @Override
                    public void execute(Boolean aBoolean) {
                        if (aBoolean) {
                            ScheduleServices.App.getInstance().publishToGCalendar(scheduleKey, new MyAsyncCallback<Void>(sendToGoogleCalendar) {
                                @Override
                                public void onSuccess(Void aVoid) {
                                    button.enable();
                                    calendarSyncData.refresh();
                                }
                            });
                        }
                    }
                });
            }
        });
        buttons.addMember(sendToGoogleCalendar);

        addMember(buttons);

        HStack labels = new HStack(5);

        authorizationLabel = new Label();
        authorizationLabel.setAutoFit(true);
        authorizationLabel.setWrap(false);
        authorizationLabel.setHeight(20);
        labels.addMember(authorizationLabel);

        labels.addMember(authorizeInGoogleCalendar);
        labels.addMember(removeAuthorization);

        lastPublished = new Label();
        lastPublished.setAutoFit(true);
        lastPublished.setWrap(false);
        lastPublished.setHeight(20);
        lastPublished.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent clickEvent) {
                if (calendarSyncData.getLastPublishErrors() != null) {
                    SC.warn(calendarSyncData.getLastPublishErrors());
                }
            }
        });
        final Label spacer = new Label("");
        spacer.setWidth(25);
        labels.addMember(spacer);
        labels.addMember(lastPublished);

        Button refreshLastUpdated = new Button(cnt().refreshButton());
        refreshLastUpdated.setAutoFit(true);
        refreshLastUpdated.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                calendarSyncData.refresh();
            }
        });
        labels.addMember(refreshLastUpdated);

        addMember(labels);


        //calendarsPanel = new DataPanel(GCalendarDS.getInstance(scheduleKey), cnt().gcalendars(), "100%", "100%", scheduleKey, true);

        addMember(calendarsListGrid);

        HLayout gridButtons = new HLayout(5);

        linkCalendarsButton = new Button(I18nUtil.cnt().addCalendarsButton());
        linkCalendarsButton.setAutoFit(true);
        linkCalendarsButton.disable();
        //GUIUtil.addAddHandler(listGrid, linkCalendarsButton, scheduleKey);
        linkCalendarsButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent clickEvent) {
                showUserCalendarsWindow(scheduleKey);
            }
        });

        com.smartgwt.client.widgets.Button removeButton = new com.smartgwt.client.widgets.Button(I18nUtil.cnt().removeButton());
        removeButton.setAutoFit(true);
        GUIUtil.addRemoveHandler(calendarsListGrid, removeButton, null);

        gridButtons.addMember(linkCalendarsButton);
        gridButtons.addMember(removeButton);

        addMember(gridButtons);

        calendarSyncData = new GCalendarSyncData(scheduleKey, new GCalendarSyncData.UpdateListener() {
            @Override
            public void afterUpdate() {
                refreshButtonsAccess();
            }
        });
    }

    private void showUserCalendarsWindow(String scheduleKey) {
        final Window window = new Window();
        window.setTitle(cnt().addCalendarsButton());
        window.setIsModal(true);
        window.setWidth(500);
        window.setHeight(400);
        window.centerInPage();

        VLayout main = new VLayout(10);
        main.setPadding(10);
        main.setWidth100();
        main.setHeight100();

        window.addItem(main);

        final ListGrid listGrid = new ListGrid();
        listGrid.setDataSource(UserGCalendarsDS.getInstance(scheduleKey));
        listGrid.setWidth100();
        listGrid.setHeight100();
        listGrid.setSelectionType(SelectionStyle.SIMPLE);
        listGrid.setShowHeader(false);
        listGrid.setAutoFetchData(true);

        main.addMember(listGrid);

        HLayout buttons = new HLayout(5);
        buttons.setHeight(15);

        Button selectButton = new Button(cnt().addCalendarsButton());
        selectButton.setAutoFit(true);
        selectButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent clickEvent) {
                final ListGridRecord[] selection = listGrid.getSelection();
                if (selection != null) {
                    GUIUtil.addDataSynchroniously(calendarsListGrid, selection);
                }
                window.hide();
            }
        });

        Button closeButton = new Button(cnt().closeButton());
        closeButton.setAutoFit(true);
        closeButton.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent clickEvent) {
                window.hide();
            }
        });

        buttons.addMember(selectButton);
        buttons.addMember(closeButton);

        main.addMember(buttons);

        window.show();
    }


    private void refreshButtonsAccess() {
        if (downloadFromGCal != null) downloadFromGCal.setDisabled(!calendarSyncData.isAuthorized());

        sendToGoogleCalendar.setDisabled(!calendarSyncData.isAuthorized());

        if (calendarSyncData.isAuthorized()) {
            authorizationLabel.setContents("<font class='okay'>" + msg().authorizationSet(calendarSyncData.getAuthorizedByUser()) + "</font>");
        } else {
            authorizationLabel.setContents("<font class='warn'>" + cnt().notAuthorizedInGCalendar() + "</font>");
        }
        linkCalendarsButton.setDisabled(!(calendarSyncData.isAuthorized() && calendarSyncData.getAuthorizedByUser().equals(scheduleUser.getEmail())));
        removeAuthorization.setVisible(calendarSyncData.isAuthorized());
        authorizeInGoogleCalendar.setVisible(!calendarSyncData.isAuthorized());

        if (calendarSyncData.getSyncStatus() == SyncStatus.FINISHED) {
            if (calendarSyncData.getLastPublishErrors() == null) {
                lastPublished.setContents(msg().publishedAt(
                        calendarSyncData.getLastPublishDate()) + " - <font class='okay'>" + cnt().successful() + "</font>");
            } else {
                lastPublished.setContents(msg().publishedAt(
                        calendarSyncData.getLastPublishDate()) + " - " + "<font class='error'>" + cnt().finishedWithErrors() + "</font>");
            }
        } else if (calendarSyncData.getSyncStatus() == SyncStatus.IN_PROGRESS) {
            lastPublished.setContents("<font class='okay'>" + msg().publishInProgress(calendarSyncData.getLastPublishDate()) + "</font>");
        }
    }

    @Override
    public void invalidateData() {
    }
}
